<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>How can I automatically convert my custom string type to and from a Python string?</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Boost.Python">
<link rel="up" href="../faq.html" title="Chapter 5. Frequently Asked Questions (FAQs)">
<link rel="prev" href="error_c2064_term_does_not_evalua.html" title="error C2064: term does not evaluate to a function taking 2 arguments">
<link rel="next" href="why_is_my_automatic_to_python_co.html" title="Why is my automatic to-python conversion not being found?">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="" width="" height="" src="../images/boost.png"></td></tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="error_c2064_term_does_not_evalua.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="why_is_my_automatic_to_python_co.html"><img src="../images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="faq.how_can_i_automatically_convert_"></a><a class="link" href="how_can_i_automatically_convert_.html" title="How can I automatically convert my custom string type to and from a Python string?">How can I automatically
      convert my custom string type to and from a Python string?</a>
</h3></div></div></div>
<p>
        <span class="emphasis"><em>Ralf W. Grosse-Kunstleve provides these notes:</em></span>
      </p>
<p>
        Below is a small, self-contained demo extension module that shows how to
        do this. Here is the corresponding trivial test:
      </p>
<pre class="programlisting"><span class="identifier">import</span> <span class="identifier">custom_string</span>
<span class="identifier">assert</span> <span class="identifier">custom_string</span><span class="special">.</span><span class="identifier">hello</span><span class="special">()</span> <span class="special">==</span> <span class="string">"Hello world."</span>
<span class="identifier">assert</span> <span class="identifier">custom_string</span><span class="special">.</span><span class="identifier">size</span><span class="special">(</span><span class="string">"california"</span><span class="special">)</span> <span class="special">==</span> <span class="number">10</span>
</pre>
<p>
        If you look at the code you will find:
      </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
            A custom <code class="computeroutput"><span class="identifier">to_python</span></code> converter
            (easy): <code class="computeroutput"><span class="identifier">custom_string_to_python_str</span></code>
          </li>
<li class="listitem">
            A custom lvalue converter (needs more code): <code class="computeroutput"><span class="identifier">custom_string_from_python_str</span></code>
          </li>
</ul></div>
<p>
        The custom converters are registered in the global Boost.Python registry
        near the top of the module initialization function. Once flow control has
        passed through the registration code the automatic conversions from and to
        Python strings will work in any module imported in the same process.
      </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">/</span><span class="identifier">module</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">/</span><span class="identifier">def</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">/</span><span class="identifier">to_python_converter</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="keyword">namespace</span> <span class="identifier">sandbox</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="special">{</span>

<span class="keyword">class</span> <span class="identifier">custom_string</span>
<span class="special">{</span>
  <span class="keyword">public</span><span class="special">:</span>
    <span class="identifier">custom_string</span><span class="special">()</span> <span class="special">{}</span>
    <span class="identifier">custom_string</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="special">&amp;</span><span class="identifier">value</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">value_</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span> <span class="special">{}</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="special">&amp;</span><span class="identifier">value</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">value_</span><span class="special">;</span> <span class="special">}</span>
  <span class="keyword">private</span><span class="special">:</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">value_</span><span class="special">;</span>
<span class="special">};</span>

<span class="keyword">struct</span> <span class="identifier">custom_string_to_python_str</span>
<span class="special">{</span>
  <span class="keyword">static</span> <span class="identifier">PyObject</span><span class="special">*</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">custom_string</span> <span class="keyword">const</span> <span class="special">&amp;</span><span class="identifier">s</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">incref</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">object</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">value</span><span class="special">()).</span><span class="identifier">ptr</span><span class="special">());</span>
  <span class="special">}</span>
<span class="special">};</span>

<span class="keyword">struct</span> <span class="identifier">custom_string_from_python_str</span>
<span class="special">{</span>
  <span class="identifier">custom_string_from_python_str</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">converter</span><span class="special">::</span><span class="identifier">registry</span><span class="special">::</span><span class="identifier">push_back</span><span class="special">(</span>
      <span class="special">&amp;</span><span class="identifier">convertible</span><span class="special">,</span>
      <span class="special">&amp;</span><span class="identifier">construct</span><span class="special">,</span>
      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">type_id</span><span class="special">&lt;</span><span class="identifier">custom_string</span><span class="special">&gt;());</span>
  <span class="special">}</span>

  <span class="keyword">static</span> <span class="keyword">void</span><span class="special">*</span> <span class="identifier">convertible</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span> <span class="identifier">obj_ptr</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">PyString_Check</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">))</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
    <span class="keyword">return</span> <span class="identifier">obj_ptr</span><span class="special">;</span>
  <span class="special">}</span>

  <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">construct</span><span class="special">(</span>
    <span class="identifier">PyObject</span><span class="special">*</span> <span class="identifier">obj_ptr</span><span class="special">,</span>
    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">converter</span><span class="special">::</span><span class="identifier">rvalue_from_python_stage1_data</span><span class="special">*</span> <span class="identifier">data</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">value</span> <span class="special">=</span> <span class="identifier">PyString_AsString</span><span class="special">(</span><span class="identifier">obj_ptr</span><span class="special">);</span>
    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">value</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">throw_error_already_set</span><span class="special">();</span>
    <span class="keyword">void</span><span class="special">*</span> <span class="identifier">storage</span> <span class="special">=</span> <span class="special">(</span>
      <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">converter</span><span class="special">::</span><span class="identifier">rvalue_from_python_storage</span><span class="special">&lt;</span><span class="identifier">custom_string</span><span class="special">&gt;*)</span>
        <span class="identifier">data</span><span class="special">)-&gt;</span><span class="identifier">storage</span><span class="special">.</span><span class="identifier">bytes</span><span class="special">;</span>
    <span class="keyword">new</span> <span class="special">(</span><span class="identifier">storage</span><span class="special">)</span> <span class="identifier">custom_string</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
    <span class="identifier">data</span><span class="special">-&gt;</span><span class="identifier">convertible</span> <span class="special">=</span> <span class="identifier">storage</span><span class="special">;</span>
  <span class="special">}</span>
<span class="special">};</span>

<span class="identifier">custom_string</span> <span class="identifier">hello</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">custom_string</span><span class="special">(</span><span class="string">"Hello world."</span><span class="special">);</span> <span class="special">}</span>

<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">(</span><span class="identifier">custom_string</span> <span class="keyword">const</span> <span class="special">&amp;</span><span class="identifier">s</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">value</span><span class="special">().</span><span class="identifier">size</span><span class="special">();</span> <span class="special">}</span>

<span class="keyword">void</span> <span class="identifier">init_module</span><span class="special">()</span>
<span class="special">{</span>
  <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>

  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">to_python_converter</span><span class="special">&lt;</span>
    <span class="identifier">custom_string</span><span class="special">,</span>
    <span class="identifier">custom_string_to_python_str</span><span class="special">&gt;();</span>

  <span class="identifier">custom_string_from_python_str</span><span class="special">();</span>

  <span class="identifier">def</span><span class="special">(</span><span class="string">"hello"</span><span class="special">,</span> <span class="identifier">hello</span><span class="special">);</span>
  <span class="identifier">def</span><span class="special">(</span><span class="string">"size"</span><span class="special">,</span> <span class="identifier">size</span><span class="special">);</span>
<span class="special">}</span>

<span class="special">}}</span> <span class="comment">// namespace sandbox::&lt;anonymous&gt;</span>

<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">custom_string</span><span class="special">)</span>
<span class="special">{</span>
  <span class="identifier">sandbox</span><span class="special">::</span><span class="identifier">init_module</span><span class="special">();</span>
<span class="special">}</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2002-2015 David
      Abrahams, Stefan Seefeld<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="error_c2064_term_does_not_evalua.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="why_is_my_automatic_to_python_co.html"><img src="../images/next.png" alt="Next"></a>
</div>
</body>
</html>
